package com.leyou.user.service;

import com.gitee.yongzhuzl.commonutil.util.empty.EmptyUtil;
import com.gitee.yongzhuzl.commonutil.util.equals.EqualsUtil;
import com.gitee.yongzhuzl.commonutil.util.random.RandomUtil;
import com.leyou.common.enums.ExceptionEnum;
import com.leyou.common.exception.LyException;
import com.leyou.user.mapper.UserMapper;
import com.leyou.user.pojo.User;
import com.leyou.user.utils.CodecUtils;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * description: 用户相关业务
 * @author 朱正磊
 * @date 2021-04-16 15:50:48
 */
@Service
public class UserService {

    @Resource
    private UserMapper userMapper;

    @Resource
    private AmqpTemplate amqpTemplate;

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    private static final String KEY_PREFIX = "user:verifyCode:phoneNumber:";

    /**
     * description: 注册请求参数校验
     * @author 朱正磊
     * @date 2021-04-16 16:02:28
     * @param data 待校验的数据
     * @param type 待校验的数据类型，1-用户名；2-手机号码
     * @return 如果校验成功则返回true，否则返回false
     */
    public Boolean checkData(String data, Integer type) {
        User user = new User();
        switch (type) {
            case 1:
                user.setUsername(data);
                break;
            case 2:
                user.setPhone(data);
                break;
            default:
                throw new LyException(ExceptionEnum.INVALID_USER_DATA_TYPE);
        }
        return userMapper.selectCount(user) == 0;
    }

    /**
     * description: 发送手机短信验证码
     * @author 朱正磊
     * @date 2021-04-16 16:41:07
     * @param phone 手机号码
     */
    public void sendCode(String phone) {
        // 生成key
        String key = KEY_PREFIX + phone;

        // 生成验证码
        // String code = NumberUtils.generateCode(6);//
        String code = RandomUtil.randomNum(6);

        Map<String, String> msg = new HashMap<>(16);
        msg.put("phoneNumber", phone);
        msg.put("code", code);

        // 发送验证码
        amqpTemplate.convertAndSend("ly.sms.txy.exchange", "sms.txy.verify.code", msg);

        // 保存验证码到redis并设置存活时长为5分钟
        stringRedisTemplate.opsForValue().set(key, code, 5, TimeUnit.MINUTES);
    }

    /**
     * description: 用户注册
     * @author 朱正磊
     * @date 2021-04-16 18:59:12
     * @param user 用户对象
     * @param code 短信验证码
     */
    public void register(User user, String code) {
        // 1、校验短信验证码
        String cacheCode = stringRedisTemplate.opsForValue().get(KEY_PREFIX + user.getPhone());
        if (EqualsUtil.isNotEquals(cacheCode, code)) {
            throw new LyException(ExceptionEnum.INVALID_VERIFY_CODE);
        }

        // 2、对密码进行MD5加密
        // 先生成盐值（唯一随机值）
        String salt = CodecUtils.generateSalt();
        user.setSalt(salt);
        // 再利用盐值对原始密码进行MD5加密
        String md5Hex = CodecUtils.md5Hex(user.getPassword(), salt);
        user.setPassword(md5Hex);

        // 3、将用户信息存入数据库
        user.setCreated(new Date());
        userMapper.insert(user);
    }

    /**
     * description: 根据用户名和密码查询用户
     * @author 朱正磊
     * @date 2021-04-17 17:02:55
     * @param username 用户名
     * @param password 密码
     * @return 返回用户信息
     */
    public User queryUserByUsernameAndPassword(String username, String password) {
        // 根据用户名查询用户
        User record = new User();
        record.setUsername(username);
        User user = userMapper.selectOne(record);

        // 校验用户名
        if (EmptyUtil.isEmpty(user)) {
            throw new LyException(ExceptionEnum.INVALID_USERNAME_PASSWORD);
        }

        // 校验密码
        if (EqualsUtil.isNotEquals(user.getPassword(), CodecUtils.md5Hex(password, user.getSalt()))) {
            throw new LyException(ExceptionEnum.INVALID_USERNAME_PASSWORD);
        }

        // 用户名和密码都正确就返回用户信息
        return user;
    }

}
